package saxon.gui.view.swing;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.text.JTextComponent;
import net.sf.saxon.s9api.XdmEmptySequence;
import net.sf.saxon.s9api.XdmItem;
import net.sf.saxon.s9api.XdmValue;
import saxon.gui.controller.XController;
import saxon.gui.view.api.XView;

/**
 *
 * @author lennyn
 */
public class SwingXView extends JFrame implements XView {

	private XController controller;
	private JSplitPane mainSplitPanel;
	private ChooseFilePanel chooseQueryFilePanel;
	private JTextComponent inputTextComponent;
	private JTextArea errorTextComponent;
	private ChooseFilePanel chooseInputFilePanel;
	private JTextField fileRegexpField;
	private OptionsPanel optionsPanel;
	private JButton execButton;
	private JTextArea outputTextComponent;
	private JButton stopButton;
	private JLabel statusLabel;
	private JTextArea shellTextArea;
	private JButton shellCommandButton;

	public SwingXView() {
		super("XGui");
		this.init();
		this.initInputPanel();
		this.initOutputPanel();
	}

	private void init() {
		try {
			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
		}
		catch (Exception ex) {
			JOptionPane.showMessageDialog(
					this,
					String.format("Failed to set look and feel: %s", ex.getMessage()),
					"Warning",
					JOptionPane.WARNING_MESSAGE);
		}
		mainSplitPanel = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
		mainSplitPanel.setResizeWeight(0.5);
		this.setLayout(new BorderLayout());
		this.add(mainSplitPanel);
		this.setVisible(true);
		this.setExtendedState(JFrame.MAXIMIZED_BOTH);
		this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
	}

	private void initInputPanel() {
		
		chooseQueryFilePanel = new ChooseFilePanel(this);
		chooseQueryFilePanel.setFileSelectionMode(JFileChooser.FILES_ONLY);
		chooseQueryFilePanel.setChooseFileListener(new ChooseFileListener() {
			@Override
			protected void fileSelected(File file) {
				controller.onQueryFileSelected(file);
			}
		});

		inputTextComponent = new JTextArea("//orth");
		inputTextComponent.setFont(Font.decode("monospaced"));
		
		JScrollPane inputScrollPane = new JScrollPane(inputTextComponent);
		inputScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
		inputScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
		inputScrollPane.setWheelScrollingEnabled(true);
		inputScrollPane.setPreferredSize(new Dimension(300, Short.MAX_VALUE));

		errorTextComponent = new JTextArea();
		errorTextComponent.setFont(Font.decode("monospaced-bold"));
		errorTextComponent.setForeground(Color.red);
		errorTextComponent.setEditable(false);
		errorTextComponent.setLineWrap(true);
		JScrollPane errScrollPane = new JScrollPane(errorTextComponent);
		errScrollPane.setWheelScrollingEnabled(true);
		errScrollPane.setMinimumSize(new Dimension(300, 60));

		execButton = new JButton();
		execButton.setText("Execute");
		execButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				controller.onClickExecute();
			}
		});

		stopButton = new JButton();
		stopButton.setText("Stop");
		stopButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				controller.onClickStop();
			}
		});

		chooseInputFilePanel = new ChooseFilePanel(this);
		chooseInputFilePanel.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
		fileRegexpField = new JTextField(".*\\.xml");
		optionsPanel = new OptionsPanel();
		statusLabel = new JLabel("  ");

		JPanel panel = new JPanel();

		panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
		panel.add(Box.createRigidArea(new Dimension(0, 20)));
		panel.add(chooseQueryFilePanel);
		panel.add(Box.createRigidArea(new Dimension(0, 15)));
		panel.add(inputScrollPane);
		panel.add(Box.createRigidArea(new Dimension(0, 15)));
		panel.add(errScrollPane);
		panel.add(Box.createRigidArea(new Dimension(0, 15)));
		panel.add(chooseInputFilePanel);
		panel.add(Box.createRigidArea(new Dimension(0, 15)));
		panel.add(new HPanel(new JLabel("Filename regexp:"), fileRegexpField, HPanel.glue()));
		panel.add(Box.createRigidArea(new Dimension(0, 15)));
		panel.add(optionsPanel);
		panel.add(Box.createRigidArea(new Dimension(0, 15)));
		panel.add(Box.createVerticalGlue());
		panel.add(new HPanel(execButton, stopButton));
		panel.add(Box.createVerticalGlue());
		panel.add(new HPanel(statusLabel));
		panel.setMinimumSize(new Dimension(200, 200));
		panel.setPreferredSize(new Dimension(300, 300));

		mainSplitPanel.setLeftComponent(panel);
	}

	private void initOutputPanel() {

		outputTextComponent = new JTextArea();
		outputTextComponent.setEditable(false);

		shellTextArea = new JTextArea();
		shellTextArea.setFont(Font.decode("monospaced"));
		shellTextArea.setEditable(true);
		shellTextArea.setText("sort | uniq");

		shellCommandButton = new JButton("Execute");
		shellCommandButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				controller.onClickShellCommandExecute();
			}
		});

		JScrollPane outScrollPane = new JScrollPane(outputTextComponent);
		outScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
		outScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
		outScrollPane.setWheelScrollingEnabled(true);
		outScrollPane.setPreferredSize(new Dimension(300, Short.MAX_VALUE));

		JScrollPane shellScrollPane = new JScrollPane(shellTextArea);
		shellScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
		shellScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
		shellScrollPane.setWheelScrollingEnabled(true);
		shellScrollPane.setPreferredSize(new Dimension(500, 300));
		shellScrollPane.setMinimumSize(new Dimension(300, 100));

		JPanel panel = new JPanel();
		panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));

		panel.add(outScrollPane);
		panel.add(Box.createVerticalGlue());
		panel.add(new HPanel(
				new VPanel(
					VPanel.space(5),
					new JLabel("Write a bash script to process your results"),
//					VPanel.space(10),
					shellScrollPane,
					shellCommandButton)));

		mainSplitPanel.setRightComponent(panel);
	}

	@Override
	public void setController(XController controller) {
		this.controller = controller;
	}
	
	@Override
	public File getQueryFile() {
		return chooseQueryFilePanel.getSelectedFile();
	}

	@Override
	public String getInputText() {
		return inputTextComponent.getText();
	}

	@Override
	public void setInputText(String xquery) {
		inputTextComponent.setText(xquery);
	}

	@Override
	public String getFileNamePattern() {
		return fileRegexpField.getText();
	}

	@Override
	public File getInputRoot() {
		return chooseInputFilePanel.getSelectedFile();
	}

	@Override
	public void clearResults() {
		outputTextComponent.setText("");
	}

	@Override
	public void addResult(File file, XdmValue val) {
		if (val instanceof XdmEmptySequence) {
			return;
		}
		else {
			for (XdmItem item : val) {
				outputTextComponent.append(item.toString());
//				System.err.println(item.getStringValue());
				outputTextComponent.append("\n");
//				System.err.println(item.toString());
			}
		}
	}

	@Override
	public void showError(String errorMsg) {
		errorTextComponent.setText(errorMsg);
	}

	@Override
	public void clearErrors() {
		errorTextComponent.setText("");
	}

	@Override
	public void setRunning(boolean running) {
		chooseInputFilePanel.setEnabled(!running);
		optionsPanel.setEnabled(!running);
		inputTextComponent.setEnabled(!running);
		execButton.setEnabled(!running);
		stopButton.setEnabled(running);
		shellCommandButton.setEnabled(!running);
		shellTextArea.setEnabled(!running);
	}

	@Override
	public LanguageChoice getLanguageChoice() {
		return optionsPanel.getLanguageChoice();
	}

	@Override
	public String getDefaultNamespace() {
		return optionsPanel.getDefaultNS();
	}

	@Override
	public void log(String msg) {
		statusLabel.setText(msg);
	}

	@Override
	public String getShellCommand() {
		return shellTextArea.getText();
	}

	@Override
	public String getOutputText() {
		return outputTextComponent.getText();
	}

	@Override
	public void showShellCommandResult(String lastQuery, String shellCommand, String res) {
		JFrame frame = new JFrame(shellCommand);
		
		JTextArea lastQueryArea = new JTextArea(lastQuery);
		lastQueryArea.setEditable(false);

		JScrollPane queryScrollPane = new JScrollPane(lastQueryArea);
		queryScrollPane.setPreferredSize(new Dimension(Short.MAX_VALUE, 100));

		JTextField shellField = new JTextField(shellCommand);
		shellField.setEditable(false);

		JTextArea resArea = new JTextArea(res);
		resArea.setEditable(false);

		JScrollPane resScrollPane = new JScrollPane(resArea);
		resScrollPane.setPreferredSize(new Dimension(Short.MAX_VALUE, Short.MAX_VALUE));

		frame.setLayout(new BorderLayout());
		frame.add(
				new HPanel(
					new VPanel(
						queryScrollPane,
						shellField,
						resScrollPane
					)));
		frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
//		frame.setSize(800, 600);
		frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		frame.pack();
		frame.setVisible(true);
	}
}
